package cn.com.twoke.application.game.mario.game.level.code;

import cn.com.twoke.application.game.mario.core.ecs.world.GameWorld;
import cn.com.twoke.application.game.mario.core.ecs.component.PositionComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.SizeComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.render.animation.AnimationRenderComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.render.group.GroupRenderComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.render.text.TextRenderComponent;
import cn.com.twoke.application.game.mario.core.ecs.component.render.texture.TextureRenderComponent;
import cn.com.twoke.application.game.mario.core.ecs.entity.Entity;
import cn.com.twoke.application.game.mario.game.component.*;
import cn.com.twoke.application.game.mario.core.ecs.level.AbstractLevel;
import cn.com.twoke.application.game.mario.game.entity.EntityType;
import cn.com.twoke.application.game.mario.game.util.TextureUtils;
import cn.com.twoke.application.game.mario.game.config.Tiles;
import lombok.RequiredArgsConstructor;

import java.awt.image.BufferedImage;
import java.util.function.Supplier;

@RequiredArgsConstructor
public class CodeLevel extends AbstractLevel {

    static BufferedImage tileset1;
    static BufferedImage marioSprite;// 精灵图

    static {
        tileset1 = TextureUtils.loadImage("texture/tileset1.png");
        marioSprite = TextureUtils.loadImage("texture/mario.png");
    }

    private static Supplier<BufferedImage> getUndergroundBlock(int x, int y) {
        BufferedImage copyImage = TextureUtils.changeColor(tileset1.getSubimage(16 * x, y, 16, 16), new int[]{0x9C4A00, 0xFFCEC5}, new int[]{0x007B8B, 0xB5EFEF});
        return () -> copyImage;
    }

    @Override
    public void init(GameWorld world) {
        // 背景
        Entity entity = world.createEntity();
        entity.addComponent(new PositionComponent(0, 0));
        entity.addComponent(new SizeComponent(Tiles.widthOf(211), Tiles.heightOf(30)));
        entity.addComponent(TextureRenderComponent.builder()
                .textureId(() -> "background")
                .build());
        // 创建地面
        entityBuilderFactory.block()
                .type(EntityType.GROUND)
                .startX(Tiles.widthOf(0))
                .startY(Tiles.heightOf(13))
                .tileCols(69)
                .tileRows(2)
                .build();

        entityBuilderFactory.block()
                .type(EntityType.GROUND)
                .startX(Tiles.widthOf(71))
                .startY(Tiles.heightOf(13))
                .tileCols(15)
                .tileRows(2)
                .build();

        entityBuilderFactory.block()
                .type(EntityType.GROUND)
                .startX(Tiles.widthOf(71))
                .startY(Tiles.heightOf(13))
                .tileCols(15)
                .tileRows(2)
                .build();

        entityBuilderFactory.block()
                .type(EntityType.GROUND)
                .startX(Tiles.widthOf(89))
                .startY(Tiles.heightOf(13))
                .tileCols(63)
                .tileRows(2)
                .build();

        entityBuilderFactory.block()
                .type(EntityType.GROUND)
                .startX(Tiles.widthOf(155))
                .startY(Tiles.heightOf(13))
                .tileCols(56).tileRows(2)
                .build();

        // 创建管道
        entityBuilderFactory.pipe()
                .startX(Tiles.widthOf(28))
                .startY(Tiles.heightOf(11))
                .build();
        entityBuilderFactory.pipe()
                .startX(Tiles.widthOf(163))
                .startY(Tiles.heightOf(11))
                .addTransferAfterHook(transfer -> {
                    if (transfer.direction == TransfersComponent.Direction.TOP) {
                        transfer.enabled = true;
                        transfer.type = TransfersComponent.TransferType.EXPORT;
                        transfer.setName("B");
                        transfer.setTargetSceneName("1_1_1");
                    }
                })
                .build();
        entityBuilderFactory.pipe()
                .startX(Tiles.widthOf(179))
                .startY(Tiles.heightOf(11))
                .build();
        entityBuilderFactory.pipe()
                .startX(Tiles.widthOf(38))
                .startY(Tiles.heightOf(10))
                .verticalLength(2)
                .build();
        entityBuilderFactory.pipe()
                .startX(Tiles.widthOf(46))
                .startY(Tiles.heightOf(9))
                .verticalLength(3)
                .build();
        entityBuilderFactory.pipe()
                .startX(Tiles.widthOf(57))
                .startY(Tiles.heightOf(9))
                .verticalLength(3)
                .addTransferAfterHook(transfer -> {
                    if (transfer.direction == TransfersComponent.Direction.TOP) {
                        transfer.enabled = true;
                        transfer.type = TransfersComponent.TransferType.ENTRY;
                        transfer.setName("A");
                    }
                })
                .build();

        // 传送门
        entityBuilderFactory.transfer()
                .startX(Tiles.widthOf(50))
                .startY(Tiles.widthOf(17))
                .width(Tiles.widthOf(1)).height(Tiles.scaleOf(2))
                .targetSceneName("1_1_2")
                .type(TransfersComponent.TransferType.EXPORT)
                .entryName("A")
                .build();

        Supplier<BufferedImage> undergroundBlockWall = getUndergroundBlock(2, 0);
        Supplier<BufferedImage> undergroundBlockGround = getUndergroundBlock(0, 0);

        entityBuilderFactory.block()
                .type(EntityType.WALL)
                .fillComponent(new BlockRenderFillComponent(undergroundBlockWall))
                .startX(Tiles.widthOf(48))
                .startY(Tiles.heightOf(17))
                .tileCols(1)
                .tileRows(11)
                .build();
        entityBuilderFactory.block()
                .type(EntityType.WALL).
                fillComponent(new BlockRenderFillComponent(undergroundBlockWall))
                .startX(Tiles.widthOf(52))
                .startY(Tiles.heightOf(17))
                .tileCols(7)
                .tileRows(1)
                .build();
        entityBuilderFactory.block()
                .type(EntityType.WALL)
                .fillComponent(new BlockRenderFillComponent(undergroundBlockWall))
                .startX(Tiles.widthOf(52))
                .startY(Tiles.heightOf(25))
                .tileCols(7)
                .tileRows(3)
                .build();

        entityBuilderFactory.block()
                .type(EntityType.GROUND)
                .fillComponent(new BlockRenderFillComponent(undergroundBlockGround))
                .startX(Tiles.widthOf(48))
                .startY(Tiles.heightOf(28))
                .tileCols(16).tileRows(2)
                .build();
        // 可进入管道
        entityBuilderFactory.pipe().startX(Tiles.widthOf(63)).startY(Tiles.heightOf(17)).verticalLength(8)
                .pipeType(PipeComponent.PipeType.J_SHAPED).isEmbeddedWall(true)
                .addTransferAfterHook(transfer -> {
                    if (transfer.direction == TransfersComponent.Direction.LEFT) {
                        transfer.enabled = true;
                        transfer.type = TransfersComponent.TransferType.ENTRY;
                        transfer.setName("B");
                    }
                })
                .extend(pipeEntity -> {
                    pipeEntity.addComponent(new TextureDealComponent(image -> TextureUtils.changeColor(image, new int[]{0x000000}, new int[]{0x084A00})));
                })
                .build();

        Entity player = entityBuilderFactory.player()
                .startX(Tiles.widthOf(3))
                .startY(Tiles.heightOf(3))
                .width(Tiles.widthOf(1))
                .height(Tiles.heightOf(1))
                .initSceneName("1_1_1")
                .initMoveSpeed(2)
                .playerName("热爱苛抵万难").build();
        PlayerComponent component = player.getComponent(PlayerComponent.class);
        GroupRenderComponent groupRenderComponent = GroupRenderComponent.builder().build();
        player.addComponent(groupRenderComponent);
        // 移动动画
        groupRenderComponent.add(AnimationRenderComponent.builder()
                .isShow(() -> (component.isLeft || component.isRight) && !component.isJump)
                .animationTickCount(3)
                .animationTickTextureFun(idx -> {
                    if (component.getDirection() == PlayerComponent.Direction.LEFT) {
                        return TextureUtils.reverse(marioSprite.getSubimage(16 + 16 * idx, 0, 16, 16));
                    } else {
                        return marioSprite.getSubimage(16 + 16 * idx, 0, 16, 16);
                    }
                })
                .build());
        // 名字
        groupRenderComponent.add(TextRenderComponent.builder()
                .text(component.name)
                .offsetY(-5)
                .build());
        // 跳跃动画
        groupRenderComponent.add(AnimationRenderComponent.builder()
                .isShow(() -> component.isJump)
                .animationTickCount(1)
                .animationTickTextureFun(idx -> {
                    if (component.getDirection() == PlayerComponent.Direction.LEFT) {
                        return TextureUtils.reverse(marioSprite.getSubimage(16 * 5, 0, 16, 16));
                    } else {
                        return marioSprite.getSubimage(16 * 5, 0, 16, 16);
                    }
                })
                .build());
        // 默认状态
        groupRenderComponent.add(AnimationRenderComponent.builder()
                .isShow(() -> !component.isJump && !component.isLeft && !component.isRight)
                .animationTickCount(1)
                .animationTickTextureFun(idx -> {
                    if (component.getDirection() == PlayerComponent.Direction.LEFT) {
                        return TextureUtils.reverse(marioSprite.getSubimage(0, 0, 16, 16));
                    } else {
                        return marioSprite.getSubimage(0, 0, 16, 16);
                    }
                })
                .build());

    }

    @Override
    public String getName() {
        return "1-1";
    }

}
